/// <summary>
/// Copyright 2010 Ivo Limmen (ivo@limmen.org)
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
/// 
/// http://www.apache.org/licenses/LICENSE-2.0
/// 
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// </summary>

using System;
using System.Timers;
using Services.TaskService.Api;
using Services.Logging.Api;

namespace Services.TaskService
{
	public class TaskExecutionMonitor
	{
		private ITask task;

		private ILogger logger;

		private DateTime? nextExecution;

		private Timer timer = new Timer();

		public TaskExecutionMonitor(ITask task, ILogger logger)
		{
			this.task = task;
			this.logger = logger;
            this.logger.Info("Loaded task...");
			
			Schedule();
        }

		private void Schedule()
		{
			this.nextExecution = this.task.GetNextExecutionTime();
			
			if (this.nextExecution.HasValue)
			{
				this.logger.Info("Scheduling...");
				
				this.timer.Interval = 500;
				this.timer.Elapsed += HandleTimerElapsed;
				this.timer.Enabled = true;
				this.timer.Start();
			}
			else
			{
				Stopped();
			}
		}

		private void Stopped()
		{
			this.logger.Info("Scheduler stopped, next execution time was not given...");
		}

		private void HandleTimerElapsed(object sender, ElapsedEventArgs eventArgs)
		{
			if (this.nextExecution.HasValue)
			{
				if (this.nextExecution.Value <= DateTime.Now)
				{
					timer.Stop();
					
					// execute the task
					try
					{
						this.task.Execute();
						
						Schedule();
					}
					catch (Exception exception)
					{
						this.logger.Error(string.Format("Execution of task '{0}' failed. Exception: ", this.task.GetName(), exception.Message));
						
						if (this.task.RescheduleAfterError())
						{
							Schedule();
						}
						else
						{
							Stopped();
						}
					}
				}
			}
		}
	}
}
